#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <windows.h>

#include "mod_ringbuffer.h"

#define BUFFER_SIZE 4096

// 使用全局数组作为缓冲区
uint8_t ringbuff[BUFFER_SIZE] = {0};

static uint32_t         validLen = 0;       // 已使用的数据长度
static uint8_t*         pHead    = NULL;    // 环形存储区的首地址
static uint8_t*         pTail    = NULL;    // 环形存储区的结尾地址
static uint8_t*         pRead    = NULL;    // 读取指针
static uint8_t*         pWrite   = NULL;    // 写入指针
static CRITICAL_SECTION buffer_cs;          // 临界区用于线程同步

/*
 * 初始化环形缓冲区
 */
void initRingbuffer(void) {
    InitializeCriticalSection(&buffer_cs);

    pHead = ringbuff;
    pTail = pHead + BUFFER_SIZE;
    pRead = pWrite = pHead;
    validLen       = 0;
}

/*
 * 向缓冲区中写入数据
 */
int writeRingbuffer(uint8_t* buffer, uint32_t addLen) {
    if (buffer == NULL || addLen == 0) {
        return -1;
    }

    EnterCriticalSection(&buffer_cs);

    // 检查是否有足够空间
    if (addLen > (BUFFER_SIZE - validLen)) {
        LeaveCriticalSection(&buffer_cs);
        return -2;    // 缓冲区空间不足
    }

    // 计算可写入的连续空间
    uint32_t contigiousSpace;
    if (pWrite >= pRead) {
        contigiousSpace = (uint32_t)(pTail - pWrite);
    } else {
        contigiousSpace = (uint32_t)(pRead - pWrite);
    }

    // 写入数据
    if (addLen <= contigiousSpace) {
        // 有足够的连续空间
        memcpy(pWrite, buffer, addLen);
        pWrite += addLen;
        if (pWrite == pTail) {
            pWrite = pHead;
        }
    } else {
        // 需要分成两段写入
        uint32_t firstPart = (uint32_t)(pTail - pWrite);
        memcpy(pWrite, buffer, firstPart);
        uint32_t secondPart = addLen - firstPart;
        memcpy(pHead, buffer + firstPart, secondPart);
        pWrite = pHead + secondPart;
    }

    validLen += addLen;

    // printf("环形buff: \n");
    // for (DWORD i = 0; i < addLen; i++) {
    //     printf("%02X ", buffer[i]);
    // }
    // printf("\n");

    LeaveCriticalSection(&buffer_cs);
    return 0;
}

/*
 * 从缓冲区内取出数据
 */
int readRingbuffer(uint8_t* buffer, uint32_t len) {
    if (buffer == NULL || len == 0) {
        return -1;
    }

    EnterCriticalSection(&buffer_cs);

    if (validLen == 0) {
        LeaveCriticalSection(&buffer_cs);
        return 0;    // 缓冲区为空
    }

    // 调整读取长度，不超过有效数据长度
    if (len > validLen) {
        len = validLen;
    }

    // 计算可读取的连续数据
    uint32_t contigiousData;
    if (pRead < pWrite) {
        contigiousData = (uint32_t)(pWrite - pRead);
    } else {
        contigiousData = (uint32_t)(pTail - pRead);
    }

    // 读取数据
    if (len <= contigiousData) {
        // 有足够的连续数据
        memcpy(buffer, pRead, len);
        pRead += len;
        if (pRead == pTail) {
            pRead = pHead;
        }
    } else {
        // 需要分成两段读取
        uint32_t firstPart = (uint32_t)(pTail - pRead);
        memcpy(buffer, pRead, firstPart);
        uint32_t secondPart = len - firstPart;
        memcpy(buffer + firstPart, pHead, secondPart);
        pRead = pHead + secondPart;
    }

    validLen -= len;

    LeaveCriticalSection(&buffer_cs);
    return len;
}

/*
 * 获取已使用缓冲区的长度
 */
uint32_t getRingbufferValidLen(void) {
    EnterCriticalSection(&buffer_cs);
    uint32_t len = validLen;
    LeaveCriticalSection(&buffer_cs);
    return len;
}

/*
 * 查看但不移除缓冲区中的数据
 */
int peekRingbuffer(uint8_t* buffer, uint32_t len) {
    if (buffer == NULL || len == 0) {
        return -1;
    }

    EnterCriticalSection(&buffer_cs);

    if (validLen == 0) {
        LeaveCriticalSection(&buffer_cs);
        return 0;    // 缓冲区为空
    }

    // 调整查看长度，不超过有效数据长度
    if (len > validLen) {
        len = validLen;
    }

    // 计算可查看的连续数据
    uint32_t contigiousData;
    if (pRead < pWrite) {
        contigiousData = (uint32_t)(pWrite - pRead);
    } else {
        contigiousData = (uint32_t)(pTail - pRead);
    }

    // 查看数据（不移动读指针）
    if (len <= contigiousData) {
        memcpy(buffer, pRead, len);
    } else {
        uint32_t firstPart = (uint32_t)(pTail - pRead);
        memcpy(buffer, pRead, firstPart);
        uint32_t secondPart = len - firstPart;
        memcpy(buffer + firstPart, pHead, secondPart);
    }

    LeaveCriticalSection(&buffer_cs);
    return len;
}

/*
 * 释放环形缓冲区（仅重置指针，不释放全局数组）
 */
void releaseRingbuffer(void) {
    EnterCriticalSection(&buffer_cs);
    // 由于使用全局数组，无需释放内存，只需重置指针和状态
    pHead    = NULL;
    pRead    = NULL;
    pWrite   = NULL;
    pTail    = NULL;
    validLen = 0;
    LeaveCriticalSection(&buffer_cs);
    DeleteCriticalSection(&buffer_cs);
}